package org.yray.sip.rtp.sender;


import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.RemovalListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.yray.sip.config.forecast.SystemProperties;
import org.yray.sip.constant.Constants;
import org.yray.sip.factory.inet.IRedo;
import org.yray.sip.log.AbstractLog;
import org.yray.sip.server.SipSession;
import org.yray.sip.utils.SerializeUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Slf4j
public class SipSessionCache implements IRedo,ISipSessionCache {

    private SystemProperties properties;

    public SipSessionCache(SystemProperties properties)
    {
        this.properties=properties;
    }

    private final static Cache<String, SipSession> sipSessionCache = Caffeine.newBuilder()
            .maximumSize(1024)
            .expireAfterWrite(Constants.CACHE_TIME, TimeUnit.SECONDS)
            .removalListener((RemovalListener<String, SipSession>) (key, value, cause) ->
                    AbstractLog.log( key , "SipSessionCache" , ", 删除原因:{}" ,cause.toString()))
            .build();

    private final static Cache<String,String> recvPortCallIdCache = Caffeine.newBuilder()
            .maximumSize(1024)
            .expireAfterWrite(Constants.CACHE_TIME, TimeUnit.SECONDS)
            .removalListener((RemovalListener<String, String>) (key, value, cause) ->
                    log.info(key,"SipSessionCache", "删除原因:{}" , cause.toString()))
            .build();
    private static Cache<Long,String> ssrcCallIdCache = Caffeine.newBuilder()
            .maximumSize(1024)
            .expireAfterWrite(Constants.CACHE_TIME, TimeUnit.SECONDS)
            .removalListener((RemovalListener<Long, String>) (key, value, cause) ->
                    log.info("ssrcCallIdCache,key:" + key + ", value:" + value + ", 删除原因:" + cause.toString()))
            .build();


    @Override
    public  void put(String callId, SipSession sipSession)
    {

        log.debug("cache sipsession,callid={}",callId.trim());
        sipSessionCache.put(callId,sipSession);
        log.info("cache sipsession,callid={}，succ",callId.trim());
    }

    @Override
    public  void removeCache(String callId)
    {
        sipSessionCache.invalidate(callId);
    }

    @Override
    public  SipSession get(String callId)
    {

        if(callId==null)
            return null;
        log.debug("get cache sipsession,callId={}",callId.trim());
        SipSession session= sipSessionCache.getIfPresent(callId.trim());
        return session;
    }

    @Override
    public  void putRecvPort(String recvPort,String callId)
    {
        AbstractLog.log(callId,"SipSessionCache","putRecvPort,recvPort={},callId={}",recvPort,callId);
        recvPortCallIdCache.put(recvPort,callId);
    }
    @Override
    public  void putSsrc2CallId(long ssrc,String callId)
    {
        AbstractLog.log(callId,"SipSessionCache","putSsrc2CallId,ssrc={},callId={}",ssrc,callId);
        ssrcCallIdCache.put(ssrc,callId);
    }
    @Override
    public  String getCallIdBySsrc(Long ssrc)
    {

       log.debug("getCallIdBySsrc,{}",ssrc);
       return ssrcCallIdCache.getIfPresent(ssrc);
    }
    @Override
    public  String getAndRemoveRecvPort(String recvPort)
    {

        String callId=recvPortCallIdCache.getIfPresent(recvPort);
        if(callId!=null) {
            recvPortCallIdCache.invalidate(recvPort);
        }
        log.debug("getAndRemoveRecvPort,recvPort={},callId={}",recvPort,callId);
        return callId;
    }

    @Override
    public   void addRtcpIp(SipSession session)
    {
        SipSession cacheSipSession=get(session.getCallId().trim());
        if(cacheSipSession==null)
        {
            log.error("addRtcpIp,cache is null callid=",session.getCallId().trim());
            return ;
        }
        cacheSipSession.setSideRtcpPort(session.getSideRtcpPort());
        cacheSipSession.setSideRtcpIp(session.getSideRtcpIp());
        cacheSipSession.setSideRtpPort(session.getSideRtpPort());

    }


    @Override
    public void redo() {
        String fileName=properties.getBackupPath()+"ssrcCallIdCache.backup";
        Map map=SerializeUtils.deserializeFile2Map(fileName);
        if(!CollectionUtils.isEmpty(map)) {
            log.info("{},redo",fileName);
            ssrcCallIdCache.putAll(map);
        }
        //备份sipSession
        fileName=properties.getBackupPath()+"sipSessionCache.backup";
        Map sipMap= SerializeUtils.deserializeFile2Map(fileName);
        if(!CollectionUtils.isEmpty(sipMap)) {
            log.info("{},redo",fileName);
            sipSessionCache.putAll(sipMap);
        }
    }

    @Override
    public void backup() {
        //备份ssrc
        String fileName=properties.getBackupPath()+"ssrcCallIdCache.backup";
        Map ssrcMap= new HashMap(ssrcCallIdCache.asMap());
        if(!CollectionUtils.isEmpty(ssrcMap)) {
            log.info("{},backup",fileName);
            SerializeUtils.serializeMap2File(ssrcMap, fileName);
        }
        //备份sipSession
        fileName=properties.getBackupPath()+"sipSessionCache.backup";
        Map sipMap= new HashMap(sipSessionCache.asMap());
        if(!CollectionUtils.isEmpty(sipMap)) {
            log.info("{},backup",fileName);
            SerializeUtils.serializeMap2File(sipMap, fileName);
        }
    }
}
